//+------------------------------------------------------------------+
//|                                              SignalEnvelopes.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert/ExpertSignal.h>    // 专家顾问信号基类（提供信号生成框架）

// wizard description start（MQL5 策略向导描述，用于识别类信息与参数）
//+------------------------------------------------------------------+
//| 类功能描述                                                       |
//| Title=基于包络线指标（Envelopes）的交易信号                        |
//| Type=SignalAdvanced                                              |
//| Name=Envelopes                                                   |
//| ShortName=Envelopes                                              |
//| Class=CSignalEnvelopes                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodMA,int,45,平均周期（包络线中间均线的计算周期）        |
//| Parameter=Shift,int,0,时间偏移（指标线相对于K线的偏移量）          |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,平均方法（中间均线的计算方式）|
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,应用价格（计算均线的基础价格）|
//| Parameter=Deviation,double,0.15,偏差率（上下轨相对于中间均线的偏离百分比）|
//+------------------------------------------------------------------+
// wizard description end

//+------------------------------------------------------------------+
//| CSignalEnvelopes 类：基于包络线指标的交易信号生成器                |
//| 核心能力：继承自 CExpertSignal，通过调用 Envelopes 指标（由“中间均线+上下轨”组成）， |
//|           识别两类多空信号（价格靠近轨线、价格突破轨线），支持通过“信号权重”和“灵敏度阈值” |
//|           调整信号触发条件，适配震荡行情的区间交易与趋势行情的突破交易       |
//| 核心逻辑：Envelopes 指标=中间均线±（均线×偏差率），上轨为压力位、下轨为支撑位；   |
//|           通过“价格是否进入轨线附近的回调区”“价格是否突破轨线外的突破区”判断信号 |
//| 适用场景：中短线区间交易与趋势突破（包络线擅长界定价格波动范围），适合外汇、股票、期货等 |
//|           品种，可单独使用或与成交量指标配合确认突破有效性               |
//+------------------------------------------------------------------+
class CSignalEnvelopes : public CExpertSignal
  {
protected:
   // 核心组件与参数（保护，子类可访问）
   CiEnvelopes       m_env;            // 包络线指标对象（封装指标计算与上下轨数据读取）
   // 包络线指标可调参数（与指标原生参数对应，默认配置兼顾波动范围覆盖与信号灵敏度）
   int               m_ma_period;      // 平均周期（中间均线的计算周期，默认45，值越大均线越平滑）
   int               m_ma_shift;       // 时间偏移（指标线右移/左移，默认0，无偏移）
   ENUM_MA_METHOD    m_ma_method;      // 平均方法（中间均线的计算方式，默认MODE_SMA，即简单移动平均）
   ENUM_APPLIED_PRICE m_ma_applied;    // 应用价格（计算均线的基础价格，默认PRICE_CLOSE，即收盘价）
   double            m_deviation;      // 偏差率（上下轨相对于中间均线的偏离百分比，默认0.15=15%）
   // 信号灵敏度阈值（控制信号触发的价格范围，默认0.2=20%，值越小信号越灵敏）
   double            m_limit_in;       // 回调区阈值（价格靠近轨线的触发范围，基于轨线间距的百分比）
   double            m_limit_out;      // 突破区阈值（价格突破轨线的触发范围，基于轨线间距的百分比）
   // 市场形态信号权重（0-100，值越大信号优先级越高，默认配置突出区间交易信号）
   int               m_pattern_0;      // 形态0权重：价格靠近目标轨线（如多单需价格靠近下轨支撑位）
   int               m_pattern_1;      // 形态1权重：价格突破目标轨线（如多单需价格突破上轨压力位）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化包络线信号生成器
    * @details 1. 初始化包络线指标对象及默认参数（周期=45、偏移=0、平均方法=SMA等）；
    *          2. 设置默认信号权重（形态0=90，形态1=70）与灵敏度阈值（回调区/突破区均为20%）；
    *          3. 启用全价格序列（开盘/最高/最低/收盘），为信号判断提供完整价格数据；
    *          4. 继承父类 CExpertSignal 的信号框架初始化
    */
                     CSignalEnvelopes(void);

   /**
    * @brief 析构函数：清理包络线信号生成器资源
    * @details 释放包络线指标对象占用的内存，依赖父类析构逻辑完成信号框架资源清理
    */
                    ~CSignalEnvelopes(void);

   //----------------------------------------------------------------
   // 包络线指标参数配置：修改核心指标参数（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置中间均线的平均周期（核心参数）
    * @param value [in] 周期值（需>0，建议20-60，值越大均线越平滑，轨线波动越平缓）
    */
   void              PeriodMA(int value);

   /**
    * @brief 设置指标时间偏移（调整轨线显示位置）
    * @param value [in] 偏移值（正数=指标线右移，负数=左移，默认0，无偏移）
    */
   void              Shift(int value);

   /**
    * @brief 设置中间均线的平均方法（调整均线平滑度）
    * @param value [in] 平均方法（ENUM_MA_METHOD 枚举，如 MODE_SMA=简单平均、MODE_EMA=指数平均）
    */
   void              Method(ENUM_MA_METHOD value);

   /**
    * @brief 设置计算均线的应用价格（调整指标基准）
    * @param value [in] 价格类型（ENUM_APPLIED_PRICE 枚举，如 PRICE_CLOSE=收盘价、PRICE_MEDIAN=中位价）
    */
   void              Applied(ENUM_APPLIED_PRICE value);

   /**
    * @brief 设置上下轨相对于中间均线的偏差率（调整轨线间距）
    * @param value [in] 偏差率（小数形式，如0.1=10%，值越大轨线间距越宽，覆盖价格波动范围越大）
    */
   void              Deviation(double value);

   //----------------------------------------------------------------
   // 信号灵敏度配置：修改回调区/突破区阈值（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置价格靠近轨线的回调区阈值（控制形态0信号灵敏度）
    * @param value [in] 阈值（小数形式，如0.2=20%，基于轨线间距的百分比，值越小越易触发信号）
    */
   void              LimitIn(double value);

   /**
    * @brief 设置价格突破轨线的突破区阈值（控制形态1信号灵敏度）
    * @param value [in] 阈值（小数形式，如0.2=20%，基于轨线间距的百分比，值越小越易触发信号）
    */
   void              LimitOut(double value);

   //----------------------------------------------------------------
   // 信号权重配置：修改不同市场形态的信号强度（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置形态0（价格靠近轨线）的信号权重
    * @param value [in] 权重值（0-100，建议80-100，值越大越重视区间交易的回调信号）
    */
   void              Pattern_0(int value);

   /**
    * @brief 设置形态1（价格突破轨线）的信号权重
    * @param value [in] 权重值（0-100，建议60-80，值越大越重视趋势突破的动量信号）
    */
   void              Pattern_1(int value);

   //----------------------------------------------------------------
   // 参数验证：确保指标参数与信号配置有效（信号生成前提）
   //----------------------------------------------------------------
   /**
    * @brief 验证包络线指标参数与信号配置的有效性
    * @return bool - 验证结果：true=所有参数有效，false=存在无效参数（如周期≤0）
    * @note 验证逻辑：
    *       1. 先调用父类 ValidationSettings() 验证信号框架基础参数（如品种、周期）；
    *       2. 额外验证中间均线周期（m_ma_period）是否>0，若无效则输出错误日志并返回false；
    *       3. 偏差率、灵敏度阈值等参数由指标内部兼容非负数值，此处不额外验证
    */
   virtual bool      ValidationSettings(void);

   //----------------------------------------------------------------
   // 指标初始化：创建并注册包络线指标（信号生成的前提）
   //----------------------------------------------------------------
   /**
    * @brief 初始化包络线指标及信号所需的价格序列数据
    * @param indicators [in] 指标集合对象（用于管理所有策略用到的指标，如包络线、成交量等）
    * @return bool - 初始化结果：true=成功（指标创建+注册到指标集合），false=失败
    * @note 调用流程：
    *       1. 先调用父类 InitIndicators() 完成基础信号框架与价格序列初始化；
    *       2. 调用内部 InitMA() 方法创建包络线指标，绑定当前品种、周期及所有指标参数；
    *       3. 若指标创建失败（如参数无效、品种不支持），返回 false 并终止信号生成
    */
   virtual bool      InitIndicators(CIndicators *indicators);

   //----------------------------------------------------------------
   // 信号判断核心方法：生成多空信号权重（策略决策依据）
   //----------------------------------------------------------------
   /**
    * @brief 判断当前市场是否满足多单（买入）开仓条件，返回信号权重
    * @return int - 多单信号权重（0-100，0=无信号，值越大信号越强烈）
    * @note 核心判断逻辑（基于包络线支撑压力特性）：
    *       1. 计算轨线间距（上轨-下轨），确定回调区与突破区范围；
    *       2. 形态0（回调买入）：收盘价进入“下轨+回调区阈值×间距”范围内（靠近下轨支撑），返回形态0权重；
    *       3. 形态1（突破买入）：收盘价突破“上轨+突破区阈值×间距”范围外（突破上轨压力），返回形态1权重；
    *       4. 优先级：形态0（默认权重90）> 形态1（默认权重70），同一时间仅取高权重信号
    */
   virtual int       LongCondition(void);

   /**
    * @brief 判断当前市场是否满足空单（卖出）开仓条件，返回信号权重
    * @return int - 空单信号权重（0-100，0=无信号，值越大信号越强烈）
    * @note 核心判断逻辑（与多单相反，基于包络线支撑压力特性）：
    *       1. 计算轨线间距（上轨-下轨），确定回调区与突破区范围；
    *       2. 形态0（回调卖出）：收盘价进入“上轨-回调区阈值×间距”范围内（靠近上轨压力），返回形态0权重；
    *       3. 形态1（突破卖出）：收盘价突破“下轨-突破区阈值×间距”范围外（突破下轨支撑），返回形态1权重；
    *       4. 优先级：形态0（默认权重90）> 形态1（默认权重70），同一时间仅取高权重信号
    */
   virtual int       ShortCondition(void);

protected:
   //----------------------------------------------------------------
   // 内部辅助方法：包络线指标初始化（仅内部调用）
   //----------------------------------------------------------------
   /**
    * @brief 创建并初始化包络线指标（绑定品种、周期、参数，注册到指标集合）
    * @param indicators [in] 指标集合对象（用于管理包络线指标）
    * @return bool - 初始化结果：true=成功（指标创建+参数配置完成），false=失败
    * @note 内部流程：
    *       1. 检查指标集合指针有效性；
    *       2. 将包络线指标对象（m_env）添加到指标集合；
    *       3. 调用 m_env.Create() 绑定当前交易品种、周期及所有指标参数（周期、偏移、平均方法等）；
    *       4. 若添加或创建失败，输出错误日志并返回 false
    */
   bool              InitMA(CIndicators *indicators);

   //----------------------------------------------------------------
   // 数据读取：快捷获取包络线上下轨数据（保护，子类可直接调用）
   //----------------------------------------------------------------
   /**
    * @brief 获取指定索引的包络线上轨值（压力位）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 上轨值（中间均线+均线×偏差率，反映价格上方压力位）
    */
   double            Upper(int ind);

   /**
    * @brief 获取指定索引的包络线下轨值（支撑位）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 下轨值（中间均线-均线×偏差率，反映价格下方支撑位）
    */
   double            Lower(int ind);
  };
//+------------------------------------------------------------------+